import 'dart:async';
import 'dart:collection';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'dialog_page.dart';
import 'navigator_controller.dart';
import 'navigator_model.dart';
import 'normal_page.dart';

//路由 核心类
class RouteDelegateDecoration extends RouterDelegate<String>
    with PopNavigatorRouterDelegateMixin<String>, ChangeNotifier {
  final Widget initialPage;

  final _pageMap = Map<String, NavigatorModel>.identity(); //可以重复key的map

  final GlobalKey<NavigatorState> navigatorKey; //父类重载

  static const SEPERATOR_PATH = "/";

  static const DIALOG_SEPERATOR_PATH = "/dialog/";

  static RouteDelegateDecoration of<T>(BuildContext context) {
    final delegate = Router.of(context).routerDelegate;
    assert(delegate is RouteDelegateDecoration, 'Delegate type must match');
    return delegate as RouteDelegateDecoration;
  }

  RouteDelegateDecoration({required this.initialPage})
      : navigatorKey = GlobalKey<NavigatorState>();

  Map<String, NavigatorModel> get pages => _pageMap; //获取整个Navigator中内容

  @override
  String? get currentConfiguration => _pageMap.isNotEmpty
      ? _pageMap.entries.last.key
      : null; //parser中restoreRouteInformation

//添加页面
  Future<T> push<T extends Object>(Widget page, {bool isDialog = false}) {
    Completer<T> result = Completer<T>();
    String path;
    if (isDialog) {
      path = DIALOG_SEPERATOR_PATH + page.toStringShort();
    } else {
      path = SEPERATOR_PATH + page.toStringShort();
    }
    _pageMap.putIfAbsent(
        path, () => NavigatorModel(page, result, isDialog: isDialog));

    notifyListeners();
    return result.future;
  }

//退出页面
  void pop<T extends Object>([T? result]) {
    Completer pagResult = _pageMap.entries.last.value.result;
    _pageMap.remove(_pageMap.entries.last.key);
    if (result != null) {
      pagResult.complete(result);
    } else {
      pagResult.complete();
    }
    notifyListeners();
  }

  //删除特定界面
  void remove({String? routeName, Widget? page, bool isdialog = false}) {
    if (routeName == null && page == null) {
      return;
    }

    String path = routeName != null ? routeName : page!.toStringShort();

    String key =
        isdialog ? DIALOG_SEPERATOR_PATH + path : SEPERATOR_PATH + path;

    //value equal  hashCode not equal
    for (var item in _pageMap.entries) {
      if (item.key == key) {
        key = item.key;
        break;
      }
    }
    if (!pages.containsKey(key) && key == initialPage.toStringShort()) {
      _pageMap.remove(NavigatorController.ROOT);
    }
    pages.remove(key);
    notifyListeners();
  }

//设置界面为root
  Future<T> pushToRoot<T extends Object>(Widget page) {
    pages.clear();
    return push(page);
  }

//设置界面替换
  Future<T> pushToReplace<T extends Object>(Widget page) {
    String key = pages.entries.last.key;

    pages.remove(key);
    return push(page);
  }

  @override
  Future<void> setNewRoutePath(String configuration) {
    _pageMap
      ..clear()
      ..putIfAbsent(
          configuration, () => NavigatorModel(initialPage, Completer()));
    return SynchronousFuture<void>(null);
  }

  bool _onPopPage(Route<dynamic> route, dynamic result) {
    if (_pageMap.isNotEmpty) {
      if (_pageMap.entries.last.key == route.settings.name) {
        Completer pagResult = _pageMap.entries.last.value.result;
        if (result != null) {
          pagResult.complete(result);
        }
        _pageMap.remove(route.settings.name);
        notifyListeners();
      }
    }
    return route.didPop(result);
  }

  @override
  Widget build(BuildContext context) {
    int count = 0;
    return Navigator(
      key: navigatorKey,
      onPopPage: _onPopPage,
      pages: [
        for (final entry in _pageMap.entries)
          if (entry.value.isDialog)
            DialogPage(
              key: ValueKey("${count++}" + entry.key), //key需要唯一，处理重复界面
              name: entry.key,
              pageBuilder: (context, __, _) {
                return entry.value.page;
              },
            )
          else
            NormalPage(
                key: ValueKey("${count++}" + entry.key), //key需要唯一，处理重复界面
                name: entry.key,
                builder: (context) {
                  return entry.value.page;
                })
      ],
    );
  }

  @override
  void dispose() {
    super.dispose();
    for (final entry in _pageMap.entries) {
      entry.value.result.complete();
    }
  }
}
